package gnippets.domain

/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
/**
 *  <p>The gnippet class is the central class within the domain.  A gnippet
 *  object is composed primarily of one or more fragments along with properties
 *  for identifying the gnippet</p>
 *
 *  @author <a href='mailto:kouphax@gmail.com'>James Hughes</a>
 *  @author <a href='mailto:dmitriy.kopylenko@gmail.com'>Dmitriy Kopylenko</a>
 */ 
class Gnippet {

    static hasMany = [
        /**
         *  List of associated code fragments that comprise the gnippet
         */    
        gniplets:Gniplet,
        
        /**
         *  List of associated tags (via Taggings)
         */        
        taggings:Tagging,
        
        /**
         *  List of associated comments
         */
        comments:Comment,

        /**
         *  Ratings for this gnippet
         */
        ratings:GnippetRating,

        /**
         *  Who added this gnippet to favorites
         */
        favoriteReferences:FavoriteGnippet
    ]
    
    static belongsTo = [user:GnippetsUser]
    
    /**
     *  Title of the gnippet
     */
    String title
    
    /**
     *  Primary Language for the gnippet (each fragment can have its own 
     *  language so this identifies the primary purpose of the gnippet)
     */
    String primaryLanguage
    
    /**
     *  Description of the overall purpose of the gnippet i.e what the gnippet
     *  is trying to achieve
     */     
    String description
    
    /**
     *  Date the gnipplet was posted
     */
    Date postDate = new Date()
    
    /**
     *  Injected service for R efCode validation
     */
    def refCodeService    
    
    static constraints = {
        title(nullable:false, blank:false)
        primaryLanguage(
            validator : { value, source ->
                /* validate entry against injected service */
                source.refCodeService.validate("language", value) 
            }         
        )
        description(nullable:false, blank:false)
        comments()
        postDate(nullable:false)
    }

    def recordOnePublicViewIfEligible(requestIp) {
       withEligibilityCheck(requestIp) {
           new GnippetWebImpressionInfo(fromIpAddress: requestIp, gnippetId: this.id,
                   whenOccurred: new Date().encodeAsMMddyyyyString()).save()
       }
   }

   def getNumberOfPublicViews() {
       GnippetWebImpressionInfo.findAllByGnippetId(this.id).size()
   }

   private def withEligibilityCheck(requestIp, capturePublicView) {
       //Hasn't been viewed from the same IP on the same day
       def n = GnippetWebImpressionInfo.withCriteria {
           and {
               eq('fromIpAddress', requestIp)
               eq('whenOccurred', new Date().encodeAsMMddyyyyString())
               eq('gnippetId', this.id)
           }
       }.size()
       if (n == 0) {
           //This is a closure passed in from the 'recordOnePublicViewIfEligible' method
           capturePublicView()
       }
   }
}